{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Advanced Features of `gamma_surface.py`\n",
    "\n",
    "## Stacking Faults of Specific Dislocations\n",
    "A feature of dislocations which make them challenging to model is that some dislocation systems can dissociate, creating two partial dislocations connected by a finite-length stacking fault. In some contexts such as in the development of Machine Learning Interatomic Potentials (MLIPs), it may be desirable to model the stacking fault in isolation.\n",
    "\n",
    "The classes `GammaSurface` and `StackingFault` offer parameterisation based on the specific classes of `matscipy.dislocation`. Instead of passing a miller index to `surface_direction`, we can instead pass a class or instance of a class that subclasses `CubicCrystalDislocation` or `CubicCrystalDissociatedDislocation` (e.g. classes like `DiamondGlideScrew`, `BCCEdge100Dislocation` or `FCCEdge110Dislocation`).\n",
    "\n",
    "As an example, the `DiamondGlideScrew` class allows the user to model the Glide Screw dislocation in diamond, which dissociates into two $30^\\circ$ partial dislocations connected by a stacking fault defined by the `surface_direction` (111) and the `glide_direction` (11-2)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from matscipy.dislocation import DiamondGlideScrew, get_elastic_constants\n",
    "from matscipy.gamma_surface import StackingFault\n",
    "from matscipy.calculators.manybody.explicit_forms.tersoff_brenner import \\\n",
    "                                   TersoffBrenner, Brenner_PRB_42_9458_C_I\n",
    "from matscipy.calculators.manybody import Manybody\n",
    "from visualisation import show_dislocation\n",
    "\n",
    "calc = Manybody(**TersoffBrenner(Brenner_PRB_42_9458_C_I))\n",
    "\n",
    "# the function accepts any ASE type of calculator\n",
    "alat, C11, C12, C44 = get_elastic_constants(calculator=calc, symbol=\"C\", verbose=False)\n",
    "print(f\"alat = {alat}\")\n",
    "C_screw = DiamondGlideScrew(alat, C11, C12, C44, symbol=\"C\")\n",
    "\n",
    "C_screw_bulk, C_screw_dislo = C_screw.build_cylinder(radius=25, partial_distance=20)\n",
    "\n",
    "view = show_dislocation(C_screw_dislo, \n",
    "                 diamond_structure=True, \n",
    "                 scale=0.6, \n",
    "                 partial_distance=20 * C_screw.glide_distance, \n",
    "                 d_name=\"1/6<112> 30 degree partial screw\") \n",
    "\n",
    "view.control.spin([0, 1, 0], np.math.pi) # flip along y-axis to align with SF visualisation\n",
    "view.control.zoom(0.7)\n",
    "view"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will use the `StackingFault` class to try and model the stacking fault we see in the above dissociated dislocation plot. The plot made use of [Common Neighbour Analysis (CNA)](https://www.ovito.org/docs/current/reference/pipelines/modifiers/common_neighbor_analysis.html) to provide useful colours for the atoms according to the identified crystal structure. This is also available in the `.show()` methods of the `StackingFault` and `GammaSurface` classes, using the `CNA_color=True` argument."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from visualisation import show_HTML\n",
    "fault = StackingFault(alat, DiamondGlideScrew, symbol=\"C\")\n",
    "fault.generate_images(n=9, cell_move=False, z_reps=2, vacuum=True)\n",
    "anim = fault.show(CNA_color=True)\n",
    "show_HTML(anim)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can see that CNA gives the same orange colour we see in the dislocation part way through the stacking fault sweep. With nine total images along the path, the middle image number five corresponds to the perfect stacking fault structure. It can be seen that atomic stacking of image five is exactly the same as the stacking fault region between two partial dislocations. This helps to confirm that we have generated a similar local structure.\n",
    "\n",
    "## Accessing Different Stacking Fault Planes\n",
    "The Diamond (111) surface is interesting, as it has two distinct planes, called \"glide\" and \"shuffle\", with the same (111) normal direction. Selection of which plane you are modelling depends on which z ordinate in the crystal basis you choose to cut at. Because in the previous example we parameterised the stacking fault with `DiamondGlideScrew` (which is a dislocation along the glide plane, as the name would suggest), we achieved a stacking fault on the glide plane. To achieve the related stacking fault on the shuffle plane, we can use the argument `z_offset` to add an offset (in Angstrom) and shift to the different plane. For this carbon crystal, an offset of 0.84 Angstrom gets us to the shuffle plane."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fault = StackingFault(alat, DiamondGlideScrew, symbol=\"C\")\n",
    "fault.generate_images(n=9, cell_move=False, z_reps=2, z_offset=0.84, vacuum=True)\n",
    "anim = fault.show(CNA_color=True)\n",
    "show_HTML(anim)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Stacking Faults in more complex systems\n",
    "`GammaSurface` and `StackingFault` generate a base structure from the input arguments in a very similar manner to the dislocation classes in `matscipy.dislocation`. This means that instead of supplying a lattice constant + symbol + crystalstructure, we can instead pass an atoms object. As an example, let's revisit GaAs from the multispecies dislocation docs:\n",
    "\n",
    ":::{note}\n",
    "As with the dislocation classes, `GammaSurface` and `StackingFault` are only guaranteed to work when passed cubic bulk crystals, and cannot themselves model chemical disorder. Any disorder effects should be applied after `generate_images()` is called.\n",
    ":::"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ase.build import bulk\n",
    "\n",
    "# Data from https://doi.org/10.1080/08927022.2011.602975\n",
    "alat = 11.2402/2\n",
    "\n",
    "GaAs = bulk(\"GaAs\", crystalstructure=\"zincblende\", cubic=True, a=alat)\n",
    "\n",
    "fault = StackingFault(GaAs, DiamondGlideScrew)\n",
    "fault.generate_images(n=9, cell_move=False, z_reps=2, vacuum=True)\n",
    "anim = fault.show(CNA_color=False)\n",
    "show_HTML(anim)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
